import numpy as np


def data_to_mem(filename):
    with open(filename, "r") as f:
        elems = []
        for line in f:
            for i in line.split():
                elems.append(eval(i))
    return elems


def file_to_np(filename, rows, cols, row_major=False):
    # 还原内存中的数据
    elems = data_to_mem(filename)
    if row_major:
        # 如果是行优先则形状和数学矩阵相同
        return np.array(elems).reshape((rows, cols))
    else:
        # 如果是列优先计算的和数据矩阵相反
        return np.array(row_major_to_col_major(elems, cols)).reshape((rows, cols))


def row_major_to_col_major(data, major):
    """
    实现将行行存储的数据在内存上依照major转换为列存储下内存布局，其中major表示按照多大间隔转换
    """
    n = len(data)
    out = list(range(n))
    assert n % major == 0, f"{n} must be divided by {major}"
    minjor = n // major
    for idx, value in enumerate(data):
        div = idx // major
        rem = idx % major
        out[rem * minjor + div] = value
    return out


def col_major_to_row_major(elems, major):
    n = len(elems)
    out = []
    assert n % major == 0, f"{n} must be divided by {major}"
    minor = n // major
    return [elems[i % major * minor + i // major] for i in range(n)]


def matmul(A, B, m, k, n, a_major_row, b_major_row, c_major):
    if a_major_row:
        A = np.array(A).reshape(m, k)
    else:
        A = np.array(col_major_to_row_major(A, k)).reshape(m, k)
    if b_major_row:
        B = np.array(B).reshape(k, n)
    else:
        B = np.array(col_major_to_row_major(B, n)).reshape(k, n)
    if c_major:
        return np.matmul(A, B)
    else:
        return np.array(
            row_major_to_col_major(np.matmul(A, B).flatten().tolist(), n)
        ).reshape(m, n)
